package ee.siimoliver.chat.server;

import java.io.IOException;
import java.util.ArrayList;

import ee.siimoliver.chat.controllers.ChatOutputController;
import ee.siimoliver.chat.controllers.ChatSessionController;
import ee.siimoliver.chat.utils.ApplicationProperties;
import ee.siimoliver.chat.utils.ChatUtils;
import ee.siimoliver.chat.utils.Const;

public class ChatSession implements ChatSessionController {

	private ArrayList<ChatMate> chatmates;
	private ChatOutputController outputController;
	
	public ChatSession(String name, String ipPort) {
		chatmates = new ArrayList<ChatMate>();
		chatmates.add(new ChatMate(name, ipPort));
	}
	
	public ChatSession(ArrayList<ChatMate> chatmates) {
		this.chatmates = chatmates;
	}
	
	@Override
	public ArrayList<ChatMate> getChatmates() {
		return chatmates;
	}

	@Override
	public boolean hasChatmate(ChatMate chatmate) {
		return chatmates.contains(chatmate);
	}

	@Override
	public void addChatmate(String chatmateName, String ipPort) {
		chatmates.add(new ChatMate(chatmateName, ipPort));
		outputController.updatePanel();
	}

	@Override
	public void sendAction(String input) throws IOException {
		boolean removed = false;
		outputController.appendText(input, ApplicationProperties.getInstance().getProperty(Const.PROP_USERNAME));
		for (int i = 0; i < chatmates.size(); i++) {
			try {
				String request = String.format("http://%s%s?%s=%s&%s=%s&%s=%s&%s=%d%s",
						chatmates.get(i).getIpPort(), Const.METHOD_SENDMESSAGE,
						Const.HEADER_KEY_MYNAME, ApplicationProperties.getInstance().getProperty(Const.PROP_USERNAME),
						Const.HEADER_KEY_MYIP, ChatUtils.getMyIpPort(),
						Const.HEADER_KEY_SENDMESSAGE, input,
						Const.HEADER_KEY_TTL, Const.TIME_TO_LIVE,
						encodeOtherMates(i));
				System.out.println(request);
				request = ChatUtils.encodeString(request, Const.IS_CUSTOM_CODING);
				System.out.println("Request: " + request);
				ChatUtils.makeGETRequestPrintResponse(request);
				chatmates.get(i).setInfo("");
			} catch (IOException e) {
				removed = true;
				chatmates.get(i).setInfo(Const.LBL_UNREACHABLE);
			}
		}
		if (removed) {
			throw new IOException("Some chatmates are unreachable!");
		}
	}

	@Override
	public String getSessionName() {
		String sessionName = "";
		for (ChatMate chatmate : chatmates) {
			sessionName += chatmate.getName() + ", ";
		}
		return sessionName.substring(0, sessionName.length() - 2);
	}

	@Override
	public void attachOutputController(ChatOutputController outputConroller) {
		this.outputController = outputConroller;
	}

	@Override
	public ChatOutputController getOutputController() {
		return outputController;
	}

	@Override
	public boolean removeChatmate(ChatMate chatmate) {
		return chatmates.remove(chatmate);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((chatmates == null) ? 0 : chatmates.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ChatSession other = (ChatSession) obj;
		if (chatmates == null) {
			if (other.chatmates != null)
				return false;
		} else if (!chatmates.equals(other.chatmates))
			return false;
		return true;
	}
	
	private String encodeOtherMates(int selfIndex) {
		String result = Const.AMPERSAND + Const.HEADER_KEY_OTHER_MATES + Const.EQUALS;
		if (chatmates.size() > 1) {
			ChatMate cm;
			for (int i = 0; i < chatmates.size(); i++) {
				if (i == selfIndex) continue;
				cm = chatmates.get(i);
				result += cm.getName() + Const.COMMA + cm.getIpPort() + Const.SEMICOLON;
			}
			return result.substring(0, result.length() - 1);
		} else return "";
	}

}
